﻿// ## 2020/11/28 # messi # 搬运NAVER论坛masterpiece可向同盟势力据点支援兵粮##
/*
	@제작 : masterpiecek
	@요청 : 엑시온
	@내용 : 자세력 거점에서 외교 메뉴를 사용해 타세력 거점에 군량을 지원
	在势力据点使用外交菜单支援其他势力据点的军粮
*/

/**
	[[[ 군량지원 외교 이벤트 개요 ]]]

	0. 거점의 외교메뉴 사용 - 메뉴를 실행한 거점에서 군량을 지원

	1. 기본 조건
	 1) 외교메뉴를 실행하는 건물이 거점일 것 (거점종류 유저설정 반영)
	 2) 실행거점의 태수가 존재할 것
	 3) 실행거점의 태수가 행동가능 상태일 것 - pk::is_idle(person); 함수 제대로 작동 안하는 것으로 보임
	 4) 실행군단의 행동력이 소모값 이상일 것
	 5) 실행세력의 기교P가 소모값 이상일 것
	 6) 실행거점의 병량이 최소 지원규모 이상일 것
	 7) 실행거점 주변에 적부대가 없을 것 (거점 주변 3칸 이내 - pk::enemies_around(building) 함수)

	2. 이벤트 실행여부 최초 확인 메시지
	 - 실행거점, 행동력 및 기교P 소모값 확인

	3. 타세력 거점 선택 - pk::building_selector() 함수 사용
	 1) 목표거점의 군량이 가득 차 있지 않을 것
	 2) 목표거점에 행동가능 무장이 있을 것 (태수가 있어도 행동완료 상태인 경우 제외됨)
	 3) 목표거점 주변에 적부대가 없을 것 (거점 주변 3칸 이내 - pk::enemies_around(building) 함수)
	 4) 실행거점세력과 목표거점세력이 동맹일 것 (동맹제한여부 유저설정 반영)
	 5) 실행(구역)도시에서 목표(구역)도시 간 거리가 도시거리 최대값 이내일 것 (최대거리 유저설정 반영)

	4. 병량 지원규모 결정 - pk::numberpad() 함수 사용
	 - 최소 지원규모 이상 최대 지원규모 이하의 범위에서 결정 가능

	5. 이벤트 실행여부 최종 확인 메시지
	 - 실행거점, 목표거점, 병량 지원규모 확인

	6. 출발 대사 출력 (메시지박스)
	 - 태수가 군주인 경우 반말 출력

	7. 이벤트 선처리
	 1) 행동력 소모 - district.ap 사용 (행동력의 경우 소모는 바로 되지만 표시가 딜레이가 있음
	 2) 기교P 소모 - pk::add_tp() 함수 사용

	8. 외교 화면 실행 - pk::scene(), pk::event::diplomacy() 함수 사용
	 - 무장 조형 애니메이션 - pk::anim() 함수 사용

	9. 도착 대사 출력 (메시지박스)
	 - 태수가 군주인 경우 반말 출력

	9. 이벤트 후처리
	 1) 태수 행동완료 설정 - person.action_done 사용
	 2) 실행거점 병량을 지원규모만큼 차감
	 3) 목표거점 병량을 지원규모만큼 가산
	 4) 각 거점 세력 간의 우호도 증가 (메시지박스 표시) - pk::add_relations() 함수 사용



	[[[ 추가로 고려 가능한 사항들 ]]]

	1. PK2.1의 정보저장 관련함수 버그 존재하여 시간의 흐름에 따른 이벤트 구현이 제약됨
	 1) 지원거리가 늘어남에 따라 행동력, 기교P 소모값이 비례하여 증가하는 방법 고려 가능
	 2) 지원이 가능한 최대거리를 제한하는 방법 고려 가능

	2. 실행거점에서 출발하는 무장을 태수가 아닌 일반무장도 가능하도록 할 것인지 여부

	3. 외교 화면에서의 대화 내용 수정여부
	 : 군주-군주, 군주-태수, 태수-군주, 태수-태수 관계를 대화에 반영할 것인지 여부 등
	[[军粮支援外交活动概要]



0. 使用据点外交菜单-在实行菜单的据点支援军粮



1. 基本条件

1）实行外交菜单的建筑物是据点（反映据点种类玩家设置）

2）执行据点的太守将存在

3）执行据点的太守可能是行动状态-pk:is idle（person）；函数似乎不正常运行

4）执行军团的行动力超过消耗值

5）执行势力的技巧P可能超过消耗值

6）执行据点的兵量至少在支援规模以上

7）执行据点周边不会有敌人部队（据点周围3格以内-pk:enemies around（building）函数）



2. 首次确认事件是否运行

-确认执行据点、行动力及技巧P消耗值



3. 选择其他势力据点-pk：building selector（）函数使用

1）目标据点的军量不会满

2）目标据点有可行动的武装（即使有太守也被排除在行动完成状态）

3）目标据点周边不会有敌人部队（据点周围3格以内-pk:enemies around（building）函数）

4）执行据点势力和目标据点势力是同盟（反映同盟限制与否玩家设定）

5）执行（区域）城市中目标（区域）城市间距离在城市距离最大值以内（反映最大距离玩家设置）



4. 决定兵量支持规模-pk:numberpad（）函数使用

-可在最小支援规模以上最大支援规模以下的范围内决定



5. 活动运行与否最终确认信息

-确认执行据点、目标据点、兵量支援规模



6. 出发台词输出（信息框）

-太守是君主的情况下，平语输出



7. 事件预处理

1）行动力消耗-district.ap 使用（行动力的情况下，消耗是可以的，但是显示有延迟

2）技巧P消耗-pk:adtp（）函数使用



8. 外交屏幕执行-pk：scene（），pk：diplomacy（）函数使用

-武装造型动画-pk：使用anim（）函数



9. 到达台词输出（信息框）

-太守是君主的情况下，平语输出



9. 事件处理

1）太守行动完成设定-person.action_done n.使用

2）执行据点兵量支援规模的差异

3）根据支援目标据点的规模加算

4）各据点势力之间的友好度增加（信息框显示）-pk:add relations（）函数使用





[[[[可以追加考虑的事项]]



1. 存在PK 2.1的信息存储相关函数错误，限制了随着时间的流逝而发生的活动

1）随着支援距离的增加，可以考虑行动力、技巧P消耗值成比例增加的方法

2）可以考虑限制可支援最大距离的方法



2. 是否能让从执行据点出发的武装不是太守而是普通武装。



3. 是否修改外交画面中的对话内容

：君主-君主，君主-太守，太守-君主，太守-太守关系是否会反映在对话中等
*/

namespace 외교_군량지원
{

	/// ========================= 유저 설정 =========================

		/// 군량지원 기본설정
	const string 군량지원_메뉴_단축키 = "";
	const string 군량지원_메뉴_이름 = "支援兵粮";
	const array<int> 군량지원_출발가능_거점형태 = { 设施_都市, 시설_관문, 시설_항구 };
	const array<int> 군량지원_도착가능_거점형태 = { 设施_都市, 시설_관문, 시설_항구 };
	const int ACTION_COST = 30;// 支援兵粮所需消耗的行动力
	const int 군량지원_소모값_기교P = 100;// 支援兵力所需消耗的技巧点
	const int 군량지원_변화값_우호도 = 30;// 支援兵力所增加的友好度

	/// 군량지원 규모설정
	const int 군량지원_지원규모_최소 = 10000;// 兵粮支援最小支援数量
	const int 군량지원_지원규모_최대 = 100000;// 兵粮支援最大支援数量

	/// 군량을 지원할 대상거점 세력의 동맹여부 제한조건
	const bool 군량지원_지원대상_동맹한정 = true;	//设置“true”?，只可向同盟势力据点支援兵粮

	/// 군량지원 도시거리 제한조건
	// 참고 : 실행거점 또는 지원대상거점이 도시가 아닌 경우에는 해당 거점구역의 도시를 기준으로 거리판단
	const bool 군량지원_거리제한_적용 = true;	// 设置“true”时，无法从执行据点支援超过一定距离的目标据点
	const int 군량지원_거리제한_거리 = 5;// 兵粮支援距离限制距离

/// =============================================================

	class Main
	{

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		pk::force@ menu_force, selected_force;
		pk::district@ menu_district;
		pk::building@ menu_base, selected_base;
		pk::person@ menu_base_taishu, selected_base_taishu;
		string menu_cost_info = "消耗行动力\x1b[1x" + ACTION_COST + "\x1b[0x,消耗技巧点\x1b[1x" + (군량지원_소모값_기교P / 2) + "\x1b[0x";
		int menu_facility_id, support_amount;
		int menu_base_taishu_id, menu_base_kunshu_id;

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		Main()
		{
			pk::menu_item item;
			item.menu = 103;
			item.shortcut = 군량지원_메뉴_단축키;
			item.init = pk::building_menu_item_init_t(init);
			item.is_visible = pk::menu_item_is_visible_t(isVisible);
			item.is_enabled = pk::menu_item_is_enabled_t(isEnabled);
			item.get_text = cast<pk::menu_item_get_text_t@>(function() { return pk::encode(군량지원_메뉴_이름); });
			item.get_desc = pk::menu_item_get_desc_t(getDesc);
			item.handler = pk::menu_item_handler_t(handler);
			pk::add_menu_item(item);
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		void init(pk::building@ building)
		{
			@menu_force = pk::get_force(building.get_force_id());
			@menu_district = pk::get_district(building.get_district_id());
			@menu_base = @building;
			menu_facility_id = building.facility;
			menu_base_taishu_id = pk::get_taishu_id(building);
			@menu_base_taishu = pk::get_person(menu_base_taishu_id);
			menu_base_kunshu_id = pk::get_kunshu_id(menu_base);
		}

		bool isVisible()
		{
			if (menu_force.get_id() != pk::get_current_turn_force_id())
				return false;

			if (군량지원_출발가능_거점형태.find(menu_facility_id) < 0)
				return false;

			return true;
		}

		bool isEnabled()
		{
			if (!pk::is_alive(menu_base_taishu))
				return false;

			if (menu_base_taishu.action_done)
				return false;

			if (int(menu_district.ap) < ACTION_COST)
				return false;

			if (int(menu_force.tp) < 군량지원_소모값_기교P)
				return false;

			if (pk::get_food(menu_base) < 군량지원_지원규모_최소)
				return false;

			if (pk::enemies_around(menu_base))
				return false;

			return true;
		}

		string getDesc()
		{
			if (!pk::is_alive(menu_base_taishu))
				return pk::encode("据点内无太守.(" + menu_cost_info + ")");

			if (menu_base_taishu.action_done)
				return pk::encode("据点内的太守已经完成行动.(" + menu_cost_info + ")");

			if (int(menu_district.ap) < ACTION_COST)
				return pk::encode("行动力不足.(" + menu_cost_info + ")");

			if (int(menu_force.tp) < 군량지원_소모값_기교P)
				return pk::encode("技巧点不足.(" + menu_cost_info + ")");

			if (pk::get_food(menu_base) < 군량지원_지원규모_최소)
				return pk::encode("据点兵粮不足.(" + menu_cost_info + ")");

			if (pk::enemies_around(menu_base))
				return pk::encode("据点周边存在敌军部队.(" + menu_cost_info + ")");

			return pk::encode("自势力据点支援其他势力据点.(" + menu_cost_info + ")");
		}

		bool handler()
		{
			func_군량지원_실행();

			return true;
		}

		void func_군량지원_실행()
		{
			string menu_base_name = "\x1b[1x" + pk::decode(pk::get_name(menu_base)) + "\x1b[0x";
			string choose_desc = menu_base_name + "是否向其他势力据点支援兵粮?\n(" + menu_cost_info + ")";
			int choose_value = pk::choose(pk::encode(choose_desc), { pk::encode("确定"), pk::encode("取消") });
			if (choose_value == /*취소*/1) return;

			pk::list<pk::building@> selectable_base_list = get_selectable_base_list();
			if (int(selectable_base_list.count) == 0) pk::message_box(pk::encode("没有可以支援兵粮的其他势力据点目标."));
			else
			{
				string selector_title = pk::encode("选择据点");
				string selector_desc = pk::encode("请选择兵粮支援的其他势力据点.");
				array<pk::building@> selected_building_arr = pk::list_to_array(pk::building_selector(selector_title, selector_desc, selectable_base_list, 1, 1));
				if (int(selected_building_arr.length) > 0)
				{
					string numberpad_title = pk::encode("支援数量");
					int support_limit = pk::min(pk::get_food(menu_base), 군량지원_지원규모_최대);
					pk::int_bool numberpad_value = pk::numberpad(numberpad_title, 군량지원_지원규모_최소, support_limit, 군량지원_지원규모_최소, pk::numberpad_t(pad_callback));
					if (numberpad_value.second)
					{
						@selected_base = selected_building_arr[0];
						//	@selected_base = pk::get_building(selected_building_arr[0].get_id());
						@selected_force = pk::get_force(selected_base.get_force_id());
						string selected_base_name = "\x1b[1x" + pk::decode(pk::get_name(selected_base)) + "\x1b[0x";
						string selected_force_name = "\x1b[2x" + pk::decode(pk::get_name(selected_force)) + "军\x1b[0x";
						support_amount = numberpad_value.first;
						string confirm_desc = menu_base_name + "是否要向" + selected_force_name + "的" + selected_base_name + "支援兵粮?\n(支援数量:\x1b[1x" + support_amount + "\x1b[0x)";
						int confirm_value = pk::choose(pk::encode(confirm_desc), { pk::encode("确定"), pk::encode("取消") });
						if (confirm_value == /*결정*/0)
						{
							func_군량지원_선처리();

							string departure_msg = "向" + selected_force_name + "的" + selected_base_name + "提供兵粮援助" + (menu_base_taishu_id == menu_base_kunshu_id ? "" : "确定") + ".";
							pk::message_box(pk::encode(departure_msg), menu_base_taishu);

							pk::scene(pk::scene_t(scene_군량지원_외교화면_실행));

							string arrival_msg = "作为支援的兵粮已经运到了" + selected_force_name + "的" + selected_base_name + "." + (menu_base_taishu_id == menu_base_kunshu_id ? "" : "确定") + ".";
							pk::message_box(pk::encode(arrival_msg), menu_base_taishu);

							func_군량지원_후처리();

							return;
						}
					}
				}
			}

			func_군량지원_실행();
		}

		void func_군량지원_선처리()
		{
			pk::add_tp(menu_force, -군량지원_소모값_기교P, menu_base.pos);
			pk::add_ap(menu_district, -ACTION_COST);
		}

		void scene_군량지원_외교화면_실행()
		{
			pk::move_screen(selected_base.get_pos(), 1000);
			int selected_base_taishu_id = pk::get_taishu_id(selected_base);
			@selected_base_taishu = pk::get_person(selected_base_taishu_id);
			int selected_base_kunshu_id = pk::get_kunshu_id(selected_base);
			pk::person@ selected_force_gunshi = pk::get_person(selected_force.gunshi);
			pk::person@ support_person = pk::get_person(무장_문관);
			if (pk::is_alive(selected_force_gunshi) and selected_base_taishu_id == selected_base_kunshu_id) @support_person = @selected_force_gunshi;
			pk::event::diplomacy(selected_base_taishu, support_person, menu_base_taishu, pk::event::diplomacy_t(diplomacy_군량지원_외교화면_대사));
			pk::move_screen(menu_base.pos, 1000);
		}

		void diplomacy_군량지원_외교화면_대사()
		{
			string menu_base_taishu_name = "\x1b[1x" + pk::decode(pk::get_name(menu_base_taishu)) + "\x1b[0x";
			string selected_base_taishu_name = "\x1b[1x" + pk::decode(pk::get_name(selected_base_taishu)) + "\x1b[0x";
			pk::anim(0, selected_base_taishu, /*제안하는듯한*/0x37);
			pk::anim(1000, menu_base_taishu, /*준비*/0x5b);
			pk::message_box(pk::encode(menu_base_taishu_name + "大人,您找我有什么事吗??"), selected_base_taishu);
			pk::message_box(pk::encode("我是来给" + selected_base_taishu_name + "阁下运送粮草来的."), menu_base_taishu);
			pk::message_box(pk::encode("刚好我军粮食不足,我正为此事发愁呢,万分感激."), selected_base_taishu);
			pk::anim(0, selected_base_taishu, /*준비*/0x5b);
			pk::anim(1000, menu_base_taishu, /*준비*/0x5b);
			pk::message_box(pk::encode("以后还望贵军多多关照."), menu_base_taishu);
			pk::play_se(12);
		}

		pk::list<pk::building@> get_selectable_base_list()
		{
			pk::list<pk::building@> base_list;
			for (int base_id = 0; base_id < 据点_末; base_id++)
			{
				pk::building@ base = pk::get_building(base_id);
				if (군량지원_도착가능_거점형태.find(base.facility) < 0) continue;
				if (군량지원_지원대상_동맹한정 and pk::is_enemy(menu_base, base)) continue;
				if (base.get_force_id() == menu_force.get_id()) continue;
				if (pk::get_food(base) == pk::get_max_food(base)) continue;
				if (int(pk::get_idle_person_list(base).count) == 0) continue;
				if (pk::enemies_around(base)) continue;

				int city_distance = get_city_distance(menu_base, base);
				if (군량지원_거리제한_적용 and city_distance > 군량지원_거리제한_거리) continue;

				base_list.add(base);
			}

			return base_list;
		}

		int get_city_distance(pk::building@ base_1, pk::building@ base_2)
		{
			int city_1_id = (base_1.get_id() < 城市_末) ? base_1.get_id() : pk::get_city_id(base_1.pos);
			int city_2_id = (base_2.get_id() < 城市_末) ? base_2.get_id() : pk::get_city_id(base_2.pos);
			return pk::get_city_distance(city_1_id, city_2_id);
		}

		string pad_callback(int line, int original_value, int current_value) { return ""; }

		void func_군량지원_후처리()
		{
			menu_base_taishu.action_done = true;
			pk::add_food(menu_base, -support_amount, true);
			pk::add_food(selected_base, support_amount, true);
			string menu_force_name = "\x1b[2x" + pk::decode(pk::get_name(menu_force)) + "军\x1b[0x";
			string selected_force_name = "\x1b[2x" + pk::decode(pk::get_name(selected_force)) + "军\x1b[0x";
			string relations_msg = menu_force_name + "和" + selected_force_name + "友好关系提升了";
			pk::message_box(pk::encode(relations_msg));
			//	pk::history_log(menu_base.pos, menu_force.color, pk::encode(relations_msg));
			pk::add_relations(menu_force, selected_force.get_id(), 군량지원_변화값_우호도);
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	}

	Main main;
}